﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace TV4Home.Server.IssueReporting
{
    public class IssueReporting
    {
        private const string issueFormUri = "https://spreadsheets.google.com/formResponse?formkey=dDB6NWI4WnQwV3UyTWlnU3BzRmN1TFE6MQ&ifq";
        private const string attachmentFormUri = "https://spreadsheets.google.com/formResponse?formkey=dGRKd3pfOGVPUFRMVi1Ya3hyT1RQN2c6MQ&ifq";

        public event UploadProgressChangedEventHandler ProgressChanged;

        public void UploadIssue(WebIssue issue, bool reportProgress = true)
        {
            try
            {
                // upload attachments
                if (issue.HasAttachments)
                {
                    foreach (WebAttachment attachment in issue.Attachments)
                    {
                        // initialize attachment parameters
                        NameValueCollection parametersAttachments = new NameValueCollection
                                                                        {
                                                                            {"entry.0.single", attachment.RelatedIssueId.ToString()},
                                                                            {"entry.1.single", attachment.AttachmentData ?? ""},
                                                                            {"entry.2.single", attachment.AttachmentFilename ?? ""},
                                                                            {"entry.3.single", attachment.AttachmentComment ?? ""},
                                                                            {"submit", "Submit"}
                                                                        };

                        Upload(attachmentFormUri, parametersAttachments, attachment.AttachmentFilename, reportProgress);
                    }
                }

                // initialize issue parameters
                NameValueCollection parametersIssue = new NameValueCollection
                                                          {
                                                              {"entry.0.single", issue.Title ?? ""},
                                                              {"entry.1.group", issue.WorkItemType ?? ""},
                                                              {"entry.6.group", issue.Priority ?? ""},
                                                              {"entry.2.single", issue.Component ?? ""},
                                                              {"entry.3.single", issue.Description ?? ""},
                                                              {"entry.5.group", (issue.HasAttachments).ToString()},
                                                              {"entry.7.single", issue.IssueId.ToString()},
                                                              {"submit", "Submit"}
                                                          };

                // upload issue
                Upload(issueFormUri, parametersIssue, "Issue data", reportProgress);
            }
            catch (Exception ex)
            {
                throw new Exception("Issue couldn't be uploaded.", ex);
            }
        }

        private void Upload(string uploadUri, NameValueCollection parameters, string itemDescription, bool reportProgress)
        {
            // upload the parameters to the online form
            using (WebClient webclient = new WebClient())
            {
                string response = "";

                if (reportProgress)
                {
                    System.Threading.ManualResetEvent wh = new System.Threading.ManualResetEvent(false);

                    webclient.UploadProgressChanged += this.ProgressChanged;
                    webclient.UploadValuesCompleted += (sender, e) =>
                                                           {
                                                               response = Encoding.ASCII.GetString(e.Result);
                                                               wh.Set();
                                                           };

                    webclient.UploadValuesAsync(new Uri(uploadUri), "POST", parameters, itemDescription);

                    // wait until upload finishes
                    wh.WaitOne();
                }
                else
                {
                    response = Encoding.ASCII.GetString(webclient.UploadValues(new Uri(uploadUri), "POST", parameters));
                }

                if (!response.Contains("3F80EFDD-E072-4240-8EE2-E57281F09FDC"))
                    throw new Exception("Response didn't contain Success GUID.");
            }
        }
    }

    public class WebIssue
    {
        public WebIssue()
        {
            this.IssueId = Guid.NewGuid();
            this.Attachments = new List<WebAttachment>();
        }

        public string Title { get; set; }
        public string WorkItemType { get; set; }
        public string Priority { get; set; }
        public string Component { get; set; }
        public string Description { get; set; }
        public Guid IssueId { get; private set; }
        public List<WebAttachment> Attachments { get; private set; }
        public bool HasAttachments { get { return this.Attachments.Count > 0; } }

        public void AddAttachment(WebAttachment attachment)
        {
            attachment.RelatedIssueId = this.IssueId;

            this.Attachments.Add(attachment);
        }

        public void AddAttachment(string filePath)
        {
            AddAttachment(File.ReadAllBytes(filePath), Path.GetFileName(filePath));
        }

        public void AddAttachment(byte[] attachmentData, string attachmentFilename, string attachmentComment = "")
        {
            this.Attachments.Add(new WebAttachment(this.IssueId)
                                     {
                                         AttachmentData = Convert.ToBase64String(attachmentData),
                                         AttachmentFilename = attachmentFilename,
                                         AttachmentComment = attachmentComment
                                     });
        }
    }

    public class WebAttachment
    {
        public WebAttachment()
        {
        }

        public WebAttachment(Guid relatedIssueId)
        {
            this.RelatedIssueId = relatedIssueId;
        }

        public string AttachmentData { get; set; }
        public string AttachmentFilename { get; set; }
        public string AttachmentComment { get; set; }
        public Guid RelatedIssueId { get; set; }
    }
}